package com.beyondsoft.mcms.domain;

import java.util.Arrays;
import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;
import org.springframework.roo.addon.tostring.RooToString;

import com.beyondsoft.mcms.common.ArrayUtil;

@RooJavaBean
@RooToString
@RooJpaActiveRecord(finders = { "findAttendeesByConferenceAndMemberInfo",
		"findAttendeesByConferenceAndMemberInfoAndAttendNameEquals" })
public class Attendee {

	/**
     */
	@NotNull
	@ManyToOne
	private Conference conference;

	/**
     */
	@NotNull
	@ManyToOne
	private MemberInfo memberInfo;

	/**
     */
	@NotNull
	private String attendName;

	/**
     */
	@NotNull
	@Pattern(regexp = "^1[0-9]{10}$")
	private String attendMobilePhone;

	/**
     */
	@NotNull
	@ManyToOne
	private Item attendStatus;

	/**
     */
	@NotNull
	private String createdBy;

	/**
     */
	private String updatedBy;

	/**
     */
	@NotNull
	@Temporal(TemporalType.TIMESTAMP)
	@DateTimeFormat(style = "MM")
	private Date createDate;

	/**
     */
	@Temporal(TemporalType.TIMESTAMP)
	@DateTimeFormat(style = "MM")
	private Date updateDate;

	private static TypedQuery<Attendee> findAttendeesByConferencesAndMemberInfoTwo(MemberInfo memberInfo,
			Conference[] conference) {
		EntityManager em = Attendee.entityManager();
		if (ArrayUtil.isEmpty(conference) && memberInfo == null) {
			TypedQuery<Attendee> q = em.createQuery("SELECT o FROM Attendee AS o ", Attendee.class);
			return q;

		} else if (memberInfo == null && !ArrayUtil.isEmpty(conference)) {
			TypedQuery<Attendee> q = em.createQuery(
					"SELECT o FROM Attendee AS o WHERE o.conference in (:conference)  ", Attendee.class);
			q.setParameter("conference", Arrays.asList(conference));
			return q;

		} else if (memberInfo != null && ArrayUtil.isEmpty(conference)) {
			TypedQuery<Attendee> q = em.createQuery("SELECT o FROM Attendee AS o WHERE o.memberInfo = :memberInfo",
					Attendee.class);
			q.setParameter("memberInfo", memberInfo);
			return q;
		} else {
			TypedQuery<Attendee> q = em.createQuery(
					"SELECT o FROM Attendee AS o WHERE o.memberInfo = :memberInfo AND o.conference in (:conference) ",
					Attendee.class);
			q.setParameter("memberInfo", memberInfo);
			q.setParameter("conference", Arrays.asList(conference));
			return q;

		}
	}

	public static TypedQuery<Attendee> findAttendeesByConferencesAndMemberInfo(MemberInfo memberInfo,
			Conference[] conference) {
		return findAttendeesByConferencesAndMemberInfoTwo(memberInfo, conference);
	}

	public static TypedQuery<Attendee> findAttendeesByConferenceAndMemberInfo(MemberInfo memberInfo,
			Conference... conference) {
		return findAttendeesByConferencesAndMemberInfoTwo(memberInfo, conference);
	}

	public static Long countAttendMemberInfo(Conference conference) {
		EntityManager em = Attendee.entityManager();
		TypedQuery<Long> q = em.createQuery(
				"SELECT count(distinct o.memberInfo )  FROM Attendee AS o WHERE o.conference = :conference ",
				Long.class);
		q.setParameter("conference", conference);
		return q.getResultList().get(0);
	}

	public static Long countAttendMemberInfo(Conference conference, Long... attendStatuses) {
		String sqlStr = "SELECT count(distinct o.memberInfo )  FROM Attendee AS o WHERE o.conference = :conference ";
		if (attendStatuses != null) {
			sqlStr += " and o.attendStatus.id in (:attendStatuses)";
		}
		EntityManager em = Attendee.entityManager();
		TypedQuery<Long> q = em.createQuery(sqlStr, Long.class);
		q.setParameter("conference", conference);
		if (attendStatuses != null) {
			q.setParameter("attendStatuses", Arrays.asList(attendStatuses));
		}
		return q.getSingleResult();
	}

	public static Long countAttendes(Conference conference, MemberInfo memberInfo, Long... attendStatuses) {
		if (conference == null && memberInfo == null && attendStatuses == null) throw new IllegalArgumentException(
				"conference,memberInfo,attendStatuses allowed are null!");
		String sqlStr = "SELECT count(o)  FROM Attendee AS o WHERE ";
		String where = null;
		if (conference != null) {
			if (StringUtils.isEmpty(where)) {
				where = "o.conference = :conference ";
			} else {
				where += " and o.conference = :conference ";
			}
		}
		if (memberInfo != null) {
			if (StringUtils.isEmpty(where)) {
				where = " o.memberInfo=:memberInfo ";
			} else {
				where += " and o.memberInfo=:memberInfo ";
			}
		}
		if (!ArrayUtil.isEmpty(attendStatuses)) {
			where += " and o.attendStatus.id in (:attendStatuses)";
		}
		EntityManager em = Attendee.entityManager();

		TypedQuery<Long> q = em.createQuery(sqlStr + where, Long.class);
		q.setParameter("conference", conference);
		if (conference != null) {
			q.setParameter("conference", conference);
		}
		if (memberInfo != null) {
			q.setParameter("memberInfo", memberInfo);
		}
		if (!ArrayUtil.isEmpty(attendStatuses)) {
			q.setParameter("attendStatuses", Arrays.asList(attendStatuses));
		}
		return q.getSingleResult();
	}

	public static Long countAttendConference(MemberInfo memberInfo, Long conferenceStatus, Long... attendStatuses) {
		String sqlStr = "SELECT count(distinct o.conference )  FROM Attendee AS o WHERE o.memberInfo = :memberInfo and o.conference.conferenceStatus.id=:conferenceStatus ";
		if (attendStatuses != null) {
			sqlStr += " and o.attendStatus.id in(:attendStatuses) ";
		}
		EntityManager em = Attendee.entityManager();
		TypedQuery<Long> q = em.createQuery(sqlStr, Long.class);
		q.setParameter("memberInfo", memberInfo);
		q.setParameter("conferenceStatus", conferenceStatus);
		if (attendStatuses != null) {
			q.setParameter("attendStatuses", Arrays.asList(attendStatuses));
		}
		return q.getSingleResult();
	}

}
